public class DataPoint {
    int dimension;
    double[] attributes;
    Cluster cluster;
    
    public DataPoint(double[] attributes) {
        this.setAttributes(attributes);
        this.dimension = attributes.length;
    }
 
    public DataPoint(Cluster cluster, double[] attributes) {
        this.setAttributes(attributes);
        this.cluster = cluster;
    }
    
    
    /**
     * @param dataPoint
     * @return squared(!) euclidean distance to dataPoint
     */
    public double getEuclideanDistanceTo(DataPoint dataPoint) {
        return Math.sqrt(this.getMinkowskiDistance2To(dataPoint, 2));
    }  
    
    public double getMinkowskiDistance2To( DataPoint dataPoint, int p) {
    	double distance = 0.0D;
        for (int i = 0; i < dimension; i++) {
        	if(attributes[i] == Double.NaN || dataPoint.attributes[i] == Double.NaN)
        		continue;
            distance += Math.pow(attributes[i] - dataPoint.attributes[i], p);
        }
    	return distance;
    }
    
    
    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder("DataPoint: ");
        for (int i = 0; i < dimension; i++) {
            stringBuilder.append(i);
            stringBuilder.append("::");
            stringBuilder.append(attributes[i]);
            stringBuilder.append(" ");
        }
        return stringBuilder.toString();
    }
    
    @Override
    public boolean equals(Object obj){
    	DataPoint newDataPoint = null;
    	if(obj.getClass() == this.getClass())
    		newDataPoint = (DataPoint) obj;
    	if(newDataPoint != null)
    		if(this.getDimension() == newDataPoint.getDimension()) {
    			for (int i = 0; i < this.getAttributes().length; i++) {
    				if(this.getAttributes()[i] != newDataPoint.getAttributes()[i])
    					return false;
				}
    			return true;
    		}
    	return false;
    }
    
    public Cluster getCluster() {
        return cluster;
    }
 
    public void setCluster(Cluster cluster) {
        this.cluster = cluster;
    }
    
    public int getDimension() {
        return dimension;
    }
 
    public double[] getAttributes() {
        return attributes;
    }

    public void setAttributes(double[] attributes) {
        this.attributes = attributes;
    }
}
